/*
 * 实现具象层，即基于BaseMessage派生出不同的请求和相应的消息类
 */
#pragma once
#include "detail.hpp"
#include "fields.hpp"
#include "abstract.hpp"

namespace jsonrpc
{
    // 定义Address类型
    using Address = std::pair<std::string, int>;

    // 定义JsonMessage类型,继承自BaseMessage,是JsonRequest和JsonResponse的基类
    class JsonMessage : public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
        virtual std::string serialize() override
        {
            std::string body;
            bool res = JsonUtil::serialize(_body, body);
            if (!res)
            {
                return std::string();
            }
            return body;
        }

        virtual bool deserialize(const std::string &msg) override
        {
            return JsonUtil::deserialize(msg, _body);
        }

    protected:
        Json::Value _body;
    };

    // 定义JsonRequest类型,继承自JsonMessage,是RpcRequest,TopicRequest,ServiceRequest的基类
    class JsonRequest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };

    // 定义JsonResponse类型,继承自JsonMessage,是RpcResponse,TopicResponse,ServiceResponse的基类
    class JsonResponse : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonResponse>;
        virtual bool check() override
        {
            if (_body[KEY_RCODE].isNull())
            {
                LOG_ERROR("response code is null");
                return false;
            }
            if (_body[KEY_RCODE].isIntegral() == false)
            {
                LOG_ERROR("response code is not integer");
                return false;
            }
            return true;
        }

        virtual RCode getRCode()
        {
            return static_cast<RCode>(_body[KEY_RCODE].asInt());
        }

        virtual void setRCode(RCode rcode)
        {
            _body[KEY_RCODE] = static_cast<int>(rcode);
        }
    };

    // 定义RpcRequest类型,继承自JsonRequest
    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;
        virtual bool check() override
        {
            // 检查rpc请求中是否包含包含method -> string, parameters->object
            if (_body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString())
            {
                LOG_ERROR("method of RpcRequest is null or not string");
                return false;
            }
            if (_body[KEY_PARAMS].isNull() || !_body[KEY_PARAMS].isObject())
            {
                LOG_ERROR("parameters of RpcRequest is null or not object");
                return false;
            }
            return true;
        };

        std::string getMethod()
        {
            return _body[KEY_METHOD].asString();
        }

        void setMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }

        Json::Value getParams()
        {
            return _body[KEY_PARAMS];
        }

        void setParams(const Json::Value &params)
        {
            _body[KEY_PARAMS] = params;
        }
    };

    // 定TopicRequest类型,继承自JsonRequest
    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        virtual bool check() override
        {
            // 检查rpc请求中是否包含包含topickey->string,optype->int
            if (_body[KEY_TOPIC_KEY].isNull() || !_body[KEY_TOPIC_KEY].isString())
            {
                LOG_ERROR("topickey of TopicRequest is null or not string");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() || !_body[KEY_OPTYPE].isIntegral())
            {
                LOG_ERROR("optype of TopicRequest is null or not integer");
                return false;
            }
            if (_body[KEY_OPTYPE].asInt() == static_cast<int>(TopicOptype::TOPIC_PUBLISH) &&
                (_body[KEY_TOPIC_MSG].isNull() || !_body[KEY_TOPIC_MSG].isString()))
            {
                LOG_ERROR("topicmsg of TopicRequest is null or not string");
                return false;
            }
            return true;
        }

        std::string getTopicKey()
        {
            return _body[KEY_TOPIC_KEY].asString();
        }

        void setTopicKey(const std::string &key)
        {
            _body[KEY_TOPIC_KEY] = key;
        }

        TopicOptype getOptype()
        {
            return static_cast<TopicOptype>(_body[KEY_OPTYPE].asInt());
        }

        void setOptype(TopicOptype optype)
        {
            _body[KEY_OPTYPE] = static_cast<int>(optype);
        }

        std::string getTopicMsg()
        {
            return _body[KEY_TOPIC_MSG].asString();
        }

        void setTopicMsg(const std::string &msg)
        {
            _body[KEY_TOPIC_MSG] = msg;
        }
    };

    // 定义ServiceRequest类型,继承自JsonRequest
    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        virtual bool check() override
        {
            // 检查rpc请求中是否包含包含method -> string, optype->int 以及host->object
            if (_body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString())
            {
                LOG_ERROR("method of ServiceRequest is null or not string");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() || !_body[KEY_OPTYPE].isIntegral())
            {
                LOG_ERROR("optype of ServiceRequest is null or not integer");
                return false;
            }
            if (_body[KEY_OPTYPE].asInt() != static_cast<int>(ServiceOptype::SERVICE_DISCOVERY) &&
                (_body[KEY_HOST].isNull() ||
                 !_body[KEY_HOST].isObject() ||
                 _body[KEY_HOST][KEY_HOST_IP].isNull() ||
                 !_body[KEY_HOST][KEY_HOST_IP].isString() ||
                 _body[KEY_HOST][KEY_HOST_PORT].isNull() ||
                 !_body[KEY_HOST][KEY_HOST_PORT].isIntegral()))
            {
                LOG_ERROR("host of ServiceRequest error");
                return false;
            }
            return true;
        }

        std::string getMethod()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }
        ServiceOptype getOptype()
        {
            return static_cast<ServiceOptype>(_body[KEY_OPTYPE].asInt());
        }
        void setOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = static_cast<int>(optype);
        }
        Address host()
        {
            Address addr;
            addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void setHost(const Address &host)
        {
            Json::Value val;
            val[KEY_HOST_IP] = host.first;
            val[KEY_HOST_PORT] = host.second;
            _body[KEY_HOST] = val;
        }
    };

    // 定义RpcResponse类型,继承自JsonResponse
    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        virtual bool check() override
        {
            // 检查rpc响应中是否包含包含rcode->int, result->object
            if (_body[KEY_RCODE].isNull() || !_body[KEY_RCODE].isIntegral())
            {
                LOG_ERROR("rcode of RpcResponse is null or not integer");
                return false;
            }
            if (_body[KEY_RESULT].isNull())//这里对结果类型不做要求
            {
                LOG_ERROR("result of RpcResponse is null");
                return false;
            }
            return true;
        }

        Json::Value getResult()
        {
            return _body[KEY_RESULT];
        }
        void setResult(const Json::Value &result)
        {
            _body[KEY_RESULT] = result;
        }
    };

    // 定义TopicResponse类型,继承自JsonResponse
    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
        // virtual bool check() 无需定义
        // 因为只需要检查 rcode ,在父类的 check() 中已经实现
    };

    // 定义ServiceResponse类型,继承自JsonResponse
    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;
        virtual bool check() override
        {
            // 检查service响应中是否包含包含rcode->int, optype->int
            if (_body[KEY_RCODE].isNull() || !_body[KEY_RCODE].isIntegral())
            {
                LOG_ERROR("rcode of ServiceResponse is null or not integer");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() || !_body[KEY_OPTYPE].isIntegral())
            {
                LOG_ERROR("optype of ServiceResponse is null or not integer");
                return false;
            }
            if (_body[KEY_OPTYPE].asInt() == static_cast<int>(ServiceOptype::SERVICE_DISCOVERY) &&
                (_body[KEY_METHOD].isNull() == true ||
                 _body[KEY_METHOD].isString() == false ||
                 _body[KEY_HOST].isNull() == true ||
                 _body[KEY_HOST].isArray() == false))
            {
                LOG_ERROR("method or host of ServiceResponse error");
                return false;
            }
            return true;
        }

        ServiceOptype getOptype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }
        void setOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = static_cast<int>(optype);
        }
        std::string getMethod()
        {
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }
        void setHost(std::vector<Address> addrs)
        {
            for (auto &addr : addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP] = addr.first;
                val[KEY_HOST_PORT] = addr.second;
                _body[KEY_HOST].append(val);
            }
        }
        std::vector<Address> hosts()
        {
            std::vector<Address> addrs;
            int size = _body[KEY_HOST].size();
            for (int i = 0; i < size; i++)
            {
                Address addr;
                addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                addrs.push_back(addr);
            }
            return addrs;
        }
    };

    // 定义生产Message的工厂类
    class MessageFactory
    {
    public:
        static BaseMessage::ptr create(MType mtype)
        {
            switch (mtype)
            {
            case MType::REQ_RPC:
                return std::make_shared<RpcRequest>();
            case MType::RSP_RPC:
                return std::make_shared<RpcResponse>();
            case MType::REQ_TOPIC:
                return std::make_shared<TopicRequest>();
            case MType::RSP_TOPIC:
                return std::make_shared<TopicResponse>();
            case MType::REQ_SERVICE:
                return std::make_shared<ServiceRequest>();
            case MType::RSP_SERVICE:
                return std::make_shared<ServiceResponse>();
            }
            return BaseMessage::ptr();
        }

        // 定义静态成员函数create,用于创建指定类型的消息对象,可以传参
        template <typename T, typename... Args>
        static std::shared_ptr<T> create(Args &&...args)
        {
            return std::make_shared<T>(std::forward(args)...);
        }
    };
}